
# 开发一个仿照 Flutter 的UI库，这里仅提供以下教学网站中提供的控件，你可以提供其它控件。
# 参考 https://flutter.cn/docs/get-started/flutter-for/web-devs

from . import flutter_icons
from . import flutter_colors


def maketag(tag, attrs=None, style=None):
    elt = javascript.document.createElement(tag)
    if attrs is not None:
        for k, v in attrs.items():
            elt.setAttribute(k, v)
    if style is not None:
        style = ';'.join([f'{k}:{v}' for k, v in style.items()])
        elt.setAttribute('style', style)
    return elt


def add_class(elt, *classes):
    classes0 = elt.getAttribute('class').data()
    if classes0 is None:
        classes0 = set()
    else:
        classes0 = set(classes0.split())
    for c in classes:
        classes0.add(c)
    elt.setAttribute('class', ' '.join(classes0))


def remove_class(elt, *classes):
    classes0 = elt.getAttribute('class').data()
    if classes0 is None:
        classes0 = set()
    else:
        classes0 = set(classes0.split())
    for c in classes:
        classes0.remove(c)
    elt.setAttribute('class', ' '.join(classes0))


Colors = flutter_colors.Colors


class EdgeInsets:
    def __init__(self, sizes):
        assert isinstance(sizes, (tuple, list))
        self.sizes = sizes

    def __repr__(self):
        return ' '.join([f'{s}px' if isinstance(s, int) else s for s in self.sizes])

    def all(sizes):
        return EdgeInsets([sizes])

    def only(top=0, right=0, bottom=0, left=0):
        return EdgeInsets([top, right, bottom, left])

    def symmetric(horizontal=0, vertical=0):
        return EdgeInsets([vertical, horizontal, vertical, horizontal])


class BorderRadius:
    def __init__(self, sizes):
        assert isinstance(sizes, (tuple, list))
        self.sizes = sizes

    def __repr__(self):
        return ' '.join([f'{s}px' if isinstance(s, int) else s for s in self.sizes])

    def all(sizes):
        return BorderRadius([sizes])

    def only(top=0, right=0, bottom=0, left=0):
        return BorderRadius([top, right, bottom, left])


class LinearGradient:
    def __init__(self, degree, colors):
        assert isinstance(degree, (int, str))
        assert isinstance(colors, (tuple, list)) and (len(colors) == 2)
        for c in colors:
            assert isinstance(c, str)
        self.degree = degree
        self.colors = colors

    def __repr__(self):
        degree = f'{self.degree}deg' if isinstance(
            self.degree, int) else self.degree
        return f'linear-gradient({degree}, {self.colors[0]}, {self.colors[1]})'


class Offset:
    def __init__(self, x, y):
        assert isinstance(x, int)
        assert isinstance(y, int)
        self.x = x
        self.y = y


class BoxShadow:
    def __init__(self, color, offset, blurRadius):
        assert isinstance(color, str)
        assert isinstance(offset, Offset)
        assert isinstance(blurRadius, int)
        self.color = color
        self.offset = offset
        self.blurRadius = blurRadius

    def __repr__(self):
        x = self.offset.x
        y = self.offset.y
        blurRadius = self.blurRadius
        if isinstance(x, int):
            x = f'{x}px'
        if isinstance(y, int):
            y = f'{y}px'
        if isinstance(blurRadius, int):
            blurRadius = f'{blurRadius}px'
        return f'{x} {y} {blurRadius} {self.color}'


class BoxShape:
    circle = 'circle'


class Container:
    def __init__(self, child, width=None, height=None, color=None, borderRadius=None,
                 gradient=None, padding=None, margin=None, boxShadow=None, shape=None):
        assert hasattr(child, 'render') and callable(child.render)
        assert (width is None) or (isinstance(width, (int, str)))
        assert (height is None) or (isinstance(height, (int, str)))
        assert (color is None) or (isinstance(color, str))
        assert (borderRadius is None) or (
            isinstance(borderRadius, BorderRadius))
        assert (gradient is None) or (isinstance(gradient, LinearGradient))
        assert (padding is None) or (isinstance(padding, EdgeInsets))
        assert (margin is None) or (isinstance(margin, EdgeInsets))
        if boxShadow is not None:
            assert isinstance(boxShadow, (tuple, list))
            for b in boxShadow:
                assert isinstance(b, BoxShadow)
        assert (shape is None) or (isinstance(shape, str))
        self.child = child
        self.width = width
        self.height = height
        self.color = color
        self.borderRadius = borderRadius
        self.gradient = gradient
        self.padding = padding
        self.margin = margin
        self.boxShadow = boxShadow
        self.shape = shape

    def render(self, parent):
        style = {}
        if self.width is not None:
            style['width'] = f'{self.width}px' if isinstance(
                self.width, int) else self.width
        if self.height is not None:
            style['height'] = f'{self.height}px' if isinstance(
                self.height, int) else self.height
        if self.color is not None:
            style['background-color'] = self.color
        if self.padding is not None:
            style['padding'] = str(self.padding)
        if self.margin is not None:
            style['margin'] = str(self.margin)
        if self.borderRadius is not None:
            style['border-radius'] = str(self.borderRadius)
        if self.gradient is not None:
            style['background'] = str(self.gradient)
        if self.boxShadow is not None:
            style['box-shadow'] = ', '.join([str(b) for b in self.boxShadow])
        if self.shape is not None:
            if self.shape == 'circle':
                style['border-radius'] = '50%'
        if hasattr(self.child, 'textAlign'):
            if self.child.textAlign is not None:
                style['text-align'] = self.child.textAlign
        e = maketag('div', style=style)
        parent.appendChild(e)
        self.child.render(e)
        javascript.mdc.topAppBar.MDCTopAppBar.new(e)
        return e


class FontWeight:
    w100 = '100'
    w200 = '200'
    w300 = '300'
    w400 = '400'
    w500 = '500'
    w600 = '600'
    w700 = '700'
    w800 = '800'
    w900 = '900'


class FontStyle:
    italic = 'italic'


class TextStyle:
    def __init__(self, fontSize=None, fontWeight=None, fontFamily=None,
                 letterSpacing=None, fontStyle=None):
        assert (fontSize is None) or isinstance(fontSize, (int, str))
        assert (fontWeight is None) or isinstance(fontWeight, str)
        assert (fontFamily is None) or isinstance(fontFamily, str)
        assert (letterSpacing is None) or (
            isinstance(letterSpacing, (int, str)))
        assert (fontStyle is None) or (isinstance(fontStyle, str))
        self.fontSize = fontSize
        self.fontWeight = fontWeight
        self.fontFamily = fontFamily
        self.letterSpacing = letterSpacing
        self.fontStyle = fontStyle

    def __repr__(self):
        style = []
        if self.fontWeight is not None:
            style.append(self.fontWeight)
        if self.fontSize is not None:
            style.append(f'{self.fontSize}px' if isinstance(
                self.fontSize, int) else self.fontSize)
        if self.fontFamily is not None:
            style.append(self.fontFamily)
        return ' '.join(style)


class TextAlign:
    center = 'center'
    left = 'left'
    right = 'right'


class TextOverflow:
    clip = 'clip'
    ellipsis = 'ellipsis'


class Text:
    def __init__(self, text, color=None, textAlign=None, style=None,
                 overflow=TextOverflow.clip, maxLines=None):
        assert (textAlign is None) or (isinstance(textAlign, str))
        assert (style is None) or (isinstance(style, TextStyle))
        assert (color is None) or (isinstance(color, str))
        assert isinstance(overflow, str)
        if maxLines is not None:
            assert isinstance(maxLines, int)
            assert maxLines >= 1
        self.text = text
        self.color = color
        self.textAlign = textAlign
        self.style = style
        self.overflow = overflow
        self.maxLines = maxLines

    def render(self, parent):
        style = {}
        if self.style is not None:
            style['font'] = str(self.style)
            if self.style.letterSpacing is not None:
                letterSpacing = self.style.letterSpacing
                if isinstance(letterSpacing, int):
                    letterSpacing = f'{letterSpacing}px'
                style['letter-spacing'] = letterSpacing
            if self.style.fontStyle is not None:
                style['font-style'] = self.style.fontStyle
        if self.color is not None:
            style['color'] = self.color
        if self.maxLines is not None:
            style['overflow'] = 'hidden'
            style['text-overflow'] = self.overflow
            style['display'] = '-webkit-box'
            style['-webkit-line-clamp'] = self.maxLines
            style['-webkit-box-orient'] = 'vertical'
        e = maketag('div', style=style)
        parent.appendChild(e)
        p = javascript.document.createTextNode(self.text)
        e.appendChild(p)
        return e


class RichText:
    def __init__(self, text):
        assert isinstance(text, TextSpan)
        self.text = text

    def render(self, parent):
        return self.text.render(parent)


class TextSpan:
    def __init__(self, text=None, color=None, style=None, children=None):
        assert (text is not None) or (children is not None)
        assert (color is None) or (isinstance(color, str))
        assert (style is None) or isinstance(style, TextStyle)
        if text is not None:
            assert isinstance(text, str)
        if children is not None:
            assert isinstance(children, (tuple, list))
            for c in children:
                assert isinstance(c, TextSpan)
        self.text = text
        self.color = color
        self.style = style
        self.children = children

    def render(self, parent):
        style = {}
        if self.style is not None:
            style['font'] = str(self.style)
            if self.style.letterSpacing is not None:
                letterSpacing = self.style.letterSpacing
                if isinstance(letterSpacing, int):
                    letterSpacing = f'{letterSpacing}px'
                style['letter-spacing'] = letterSpacing
            if self.style.fontStyle is not None:
                style['font-style'] = self.style.fontStyle
        if self.color is not None:
            style['color'] = self.color
        e = maketag('span', style=style)
        parent.appendChild(e)
        if self.text is not None:
            p = javascript.document.createTextNode(self.text)
            e.appendChild(p)
        elif self.children is not None:
            for c in self.children:
                c.render(e)
        return e


class Center:
    def __init__(self, child):
        assert hasattr(child, 'render') and callable(child.render)
        self.child = child

    def render(self, parent):
        e = maketag('div', style={'display': 'flex', 'align-items': 'center',
                                  'justify-content': 'center', 'width': '100%', 'height': '100%'})
        parent.appendChild(e)
        self.child.render(e)

        javascript.mdc.topAppBar.MDCTopAppBar.new(e)

        return e


class Stack:
    def __init__(self, children):
        assert isinstance(children, (tuple, list))
        for c in children:
            assert isinstance(c, Positioned)
        self.children = children

    def render(self, parent):
        e = maketag('div', style={'position': 'relative'})
        for c in self.children:
            c.render(e)
        return e


class Positioned:
    def __init__(self, child, left, top):
        assert hasattr(child, 'render') and callable(child.render)
        assert isinstance(left, (int, str))
        assert isinstance(top, (int, str))
        self.child = child
        self.left = left
        self.top = top

    def render(self, parent):
        top = f'{self.top}px' if isinstance(self.top, int) else self.top
        left = f'{self.left}px' if isinstance(self.left, int) else self.left
        e = maketag(
            'div', style={'position': 'absolute', 'top': top, 'left': left})
        parent.appendChild(e)
        self.child.render(e)
        return e


class Transform:
    def __init__(self, child, rotate=None, scale=None):
        assert hasattr(child, 'render') and callable(child.render)
        assert (rotate is None) or isinstance(rotate, (int, str))
        assert (scale is None) or isinstance(scale, float)
        self.child = child
        self.rotate = rotate
        self.scale = scale

    def render(self, parent):
        transform = []
        if self.rotate is not None:
            rotate = f'{self.rotate}deg' if isinstance(
                self.rotate, int) else self.rotate
            transform.append(f'rotate({rotate})')
        if self.scale is not None:
            transform.append(f'scale({self.scale})')
        e = maketag('div')
        parent.appendChild(e)
        if len(transform) > 0:
            e.style.transform = ' '.join(transform)
        self.child.render(e)
        return e


# https://www.cnblogs.com/hellocd/p/10443237.html

class Axis:  # flex-direction
    horizontal = 'row'
    vertical = 'column'


class MainAxisAlignment:  # justify-content
    center = 'center'
    end = 'flex-end'
    spaceAround = 'space-around'
    spaceBetween = 'space-between'
    spaceEvenly = 'space-evenly'
    start = 'flex-start'


class CrossAxisAlignment:  # align-items
    baseline = 'baseline'
    center = 'center'
    end = 'end'
    start = 'start'
    stretch = 'stretch'


class MainAxisSize:
    max = 'max'
    min = 'min'


class Flex:
    def __init__(self, children, direction,
                 mainAxisAlignment=MainAxisAlignment.start,
                 crossAxisAlignment=CrossAxisAlignment.center,
                 mainAxisSize=MainAxisSize.min):
        assert isinstance(children, (tuple, list))
        for child in children:
            assert hasattr(child, 'render') and callable(
                child.render), type(child).__name__
        self.children = children
        assert direction in (Axis.horizontal, Axis.vertical)
        assert mainAxisAlignment in (MainAxisAlignment.center,
                                     MainAxisAlignment.end,
                                     MainAxisAlignment.spaceAround,
                                     MainAxisAlignment.spaceBetween,
                                     MainAxisAlignment.spaceEvenly,
                                     MainAxisAlignment.start)
        assert crossAxisAlignment in (CrossAxisAlignment.baseline,
                                      CrossAxisAlignment.center,
                                      CrossAxisAlignment.end,
                                      CrossAxisAlignment.start,
                                      CrossAxisAlignment.stretch)
        assert mainAxisSize in (MainAxisSize.max,
                                MainAxisSize.min)
        self.direction = direction
        self.mainAxisAlignment = mainAxisAlignment
        self.crossAxisAlignment = crossAxisAlignment
        self.mainAxisSize = mainAxisSize

    def render(self, parent):
        style = {'display': 'flex',
                 'flex-direction': self.direction,
                 'flex-wrap': 'nowrap',
                 'justify-content': self.mainAxisAlignment,
                 'align-items': self.crossAxisAlignment}
        if self.mainAxisSize == MainAxisSize.max:
            if self.direction == 'row':
                style['width'] = '100%'
            else:
                style['height'] = '100%'
        e = maketag('div', style=style)
        parent.appendChild(e)
        for child in self.children:
            child.render(e)
        return e


class Row(Flex):
    def __init__(self, children,
                 mainAxisAlignment=MainAxisAlignment.start,
                 crossAxisAlignment=CrossAxisAlignment.center,
                 mainAxisSize=MainAxisSize.min):
        super(Row, self).__init__(children,
                                  direction=Axis.horizontal,
                                  mainAxisAlignment=mainAxisAlignment,
                                  crossAxisAlignment=crossAxisAlignment,
                                  mainAxisSize=mainAxisSize)


class Column(Flex):
    def __init__(self, children,
                 mainAxisAlignment=MainAxisAlignment.start,
                 crossAxisAlignment=CrossAxisAlignment.center,
                 mainAxisSize=MainAxisSize.min):
        super(Column, self).__init__(children,
                                     direction=Axis.vertical,
                                     mainAxisAlignment=mainAxisAlignment,
                                     crossAxisAlignment=crossAxisAlignment,
                                     mainAxisSize=mainAxisSize)


# MDC (Material Design Components)

class Scaffold:
    def __init__(self, appBar, body):
        assert hasattr(appBar, 'render') and callable(appBar.render)
        assert hasattr(body, 'render') and callable(body.render)
        self.appBar = appBar
        self.body = body

    def render(self, parent):
        scafflod_height = javascript.document.documentElement.clientHeight.data()
        e = maketag('div', style={
                    'display': 'flex', 'flex-flow': 'column', 'height': f'{scafflod_height}px'})
        header = maketag('header', {'class': 'mdc-top-app-bar mdc-top-app-bar--fixed'},
                         style={'flex': '0 1 auto'})
        parent.appendChild(e)
        e.appendChild(header)
        main = maketag('header', {'class': 'mdc-top-app-bar--fixed-adjust'},
                       style={'flex': '1 1 auto'})
        e.appendChild(main)
        self.appBar.render(header)
        self.body.render(main)
        self.topAppBar = javascript.mdc.topAppBar.MDCTopAppBar.new(e)
        return e


class AppBar:
    def __init__(self, leading=None, title=None, actions=None):
        if leading is not None:
            assert hasattr(leading, 'render') and callable(leading.render)
        if title is not None:
            assert hasattr(title, 'render') and callable(title.render)
        if actions is not None:
            assert isinstance(actions, (tuple, list))
            for action in actions:
                assert hasattr(action, 'render') and callable(action.render)
        self.leading = leading
        self.title = title
        self.actions = actions

    def render(self, parent):
        e = maketag('div', {'class': 'mdc-top-app-bar__row'})
        parent.appendChild(e)
        start = maketag('header', {
                        'class': 'mdc-top-app-bar__section mdc-top-app-bar__section--align-start'})
        e.appendChild(start)
        end = maketag('header', {
                      'class': 'mdc-top-app-bar__section mdc-top-app-bar__section--align-end', 'rule': 'toolbar'})
        e.appendChild(end)
        if self.leading is not None:
            leading = self.leading.render(start)
            add_class(leading, 'mdc-top-app-bar__navigation-icon')
        if self.title is not None:
            title = self.title.render(start)
            add_class(title, 'mdc-top-app-bar__title')
        if self.actions is not None:
            for action in self.actions:
                action = action.render(end)
                add_class(action, 'mdc-top-app-bar__action-item')
        return e


class IconButton:
    def __init__(self, icon, onPressed=None):
        assert isinstance(icon, Icon)
        if onPressed is not None:
            assert callable(onPressed)
        self.icon = icon
        self.onPressed = onPressed

    def render(self, parent):
        e = maketag('button', {
                    'class': 'material-icons mdc-top-app-bar__action-item mdc-icon-button'})
        parent.appendChild(e)
        e.appendChild(javascript.document.createTextNode(self.icon.icon))
        if self.onPressed is not None:
            e.bind('click', self.onPressed)
        javascript.mdc.ripple.MDCRipple.new(e)
        return e


class Icon:
    def __init__(self, icon):
        assert isinstance(icon, str)
        self.icon = icon

    def render(self, parent):
        e = maketag('span', {'class': 'material-icons'})
        parent.appendChild(e)
        e.appendChild(javascript.document.createTextNode(self.icon))
        return e


Icons = flutter_icons.Icons

# TODO
# https://material.io/components/banners
# https://material.io/components/buttons
# https://material.io/components/cards
# https://material.io/components/checkboxes
# https://material.io/components/chips
# https://material.io/components/data-tables
# https://material.io/components/dialogs
# https://material.io/components/lists
# https://material.io/components/menus
# https://material.io/components/navigation-drawer
# https://material.io/components/radio-buttons
# https://material.io/components/sheets-side
# https://material.io/components/snackbars
# https://material.io/components/switches
# https://material.io/components/tabs
# https://material.io/components/text-fields
# https://material.io/components/tooltips


# class Avatar:
#     def __init__(self, img, alt=None, width=None, height=None):

#         self.img = img
#         self.alt = alt
#         self.width = width
#         self.height = height

#     def render(self):
#         e = maketag("img", {"src": self.img})
#         return e


# class Chip:
#     def __init__(self, avatar, label, onDelete=None):
#         self.avator = avatar
#         self.label = label
#         self.onDelete = onDelete

#     def render(self):
#         assert isinstance(self.avator, Avatar)
#         assert isinstance(self.label, Text)

#         e = maketag("div", {"class": "chip"})
#         e.appendChild(self.avator.render())
#         e.appendChild(self.label.render())

#         if self.onDelete != None:
#             tmp = maketag("span", {
#                           "class": "closebtn", "onclick": "this.parentElement.style.display='none'"})
#             tmp.appendChild(javascript.document.createTextNode("x"))

#             e.appendChild(tmp)

#         return e


class Action:
    def __init__(self, label, avatar=None, deleted=False, selected=False, onSelected=None, disabled=False):
        self.label = label
        self.deleted = deleted
        self.avatar = avatar
        self.selected = selected
        self.onSelected = onSelected
        self.disabled = disabled

    def render(self, parent):

        e = None

        buttonAttr = {"class": "mdc-evolution-chip__action mdc-evolution-chip__action--primary",
                      "type": "button", "tabindex": "0"}
        #buttonAttr = {"class":"mdc-evolution-chip__action mdc-evolution-chip__action--primary", "aria-selected":"false","tabindex":"0"}

        if self.deleted:
            buttonAttr["data-mdc-deletable"] = "true"

        if self.selected:
            buttonAttr["role"] = "option"

        # TODO: 需要添加对 disabled 的支持
        if self.disabled:
            pass

        e = maketag("button", buttonAttr)

        parent.appendChild(e)

        child1 = maketag("span", {
                         "class": "mdc-evolution-chip__ripple mdc-evolution-chip__ripple--primary"})
        e.appendChild(child1)

        # assert hasattr(self.label, 'render') and callable(self.label.render)
        # child2 = self.label.render()
        child_graphic = None
        if self.avatar != None:
            assert isinstance(self.avatar, Icon)
            child_graphic = maketag(
                "span", {"class": "mdc-evolution-chip__graphic"})

            icons = maketag("span", {
                            "class": "mdc-evolution-chip__icon mdc-evolution-chip__icon--primary material-icons"})
            icons.appendChild(
                javascript.document.createTextNode(self.avatar.icon))

            child_graphic.appendChild(icons)
            # child_graphic.appendChild(self.avatar.render())

        if self.selected:
            print("here")
            if child_graphic == None:
                child_graphic = maketag(
                    "span", {"class": "mdc-evolution-chip__graphic"})

            checkmark = maketag(
                "span", {"class": "mdc-evolution-chip__checkmark"})

            checkmark_svg = _make_svg(
                "svg", {"class": "mdc-evolution-chip__checkmark-svg", "viewBox": "-2 -3 30 30"})

            checkmark_path = _make_svg("path", {"class": "mdc-evolution-chip__checkmark-path",
                                       "fill": "none", "stroke": "black", "d": "M1.73,12.91 8.1,19.28 22.79,4.59"})

            checkmark_svg.appendChild(checkmark_path)
            checkmark.appendChild(checkmark_svg)
            child_graphic.appendChild(checkmark)

        if child_graphic != None:
            e.appendChild(child_graphic)

        chip_text_label = maketag(
            "span", {"class": "mdc-evolution-chip__text-label"})
        chip_text_label.appendChild(
            javascript.document.createTextNode(self.label.text))
        e.appendChild(chip_text_label)

        # javascript.mdc.topAppBar.MDCTopAppBar.new(e)

        return e


class TrailingAction:
    def __init__(self, label, deletable=True):
        self.label = label
        self.deletable = deletable

    def render(self, parent):
        buttonAttr = {"class": "mdc-evolution-chip__action mdc-evolution-chip__action--trailing",
                      "type": "button", "tabindex": "-1", "data-mdc-deletable": "true", "aria-hidden": "true"}

        e = maketag("button", buttonAttr)
        parent.appendChild(e)

        ripple = maketag("span", {
                         "class": "mdc-evolution-chip__ripple mdc-evolution-chip__ripple--trailing"})

        e.appendChild(ripple)

        text = maketag(
            "span", {"class": "mdc-evolution-chip__icon mdc-evolution-chip__icon--trailing"})
        e.appendChild(text)

        text.appendChild(javascript.document.createTextNode(self.label.text))
        # javascript.mdc.topAppBar.MDCTopAppBar.new(e)
        return e


class ActionChip:
    def __init__(self, label, avatar=None, deleted=False, selected=False, onSelected=None, disabled=False):
        self.label = label
        self.deleted = deleted
        self.avatar = avatar
        self.selected = selected
        self.onSelected = onSelected
        self.disabled = disabled

    def render(self, parent):
        e = maketag("span", {"class": "mdc-evolution-chip",
                    "role": "row", "id": "c0"})
        if self.disabled:
            e = maketag(
                "span", {"class": "mdc-evolution-chip--disabled", "role": "row", "id": "c0"})
        parent.appendChild(e)

        chip_cell = maketag("span", {
                            "class": "mdc-evolution-chip__cell mdc-evolution-chip__cell--primary", "role": "gridcell"})
        e.appendChild(chip_cell)

        action = Action(label=self.label, avatar=self.avatar, deleted=self.deleted,
                        selected=self.selected, onSelected=self.onSelected, disabled=self.disabled)
        chip_cell.appendChild(action.render(parent))
        # javascript.mdc.topAppBar.MDCTopAppBar.new(e)
        return e


class InputChip:
    def __init__(self, label, label1=Text("test")):
        self.label = label
        self.label1 = label1

    def render(self, parent):

        e = maketag("span", {"class": "mdc-evolution-chip",
                    "role": "presentation", "id": "c3"})
        parent.appendChild(e)

        chip_cell = maketag("span", {
                            "class": "mdc-evolution-chip__cell mdc-evolution-chip__cell--primary", "role": "gridcell"})
        e.appendChild(chip_cell)

        action1 = Action(label=self.label)
        chip_cell.appendChild(action1.render(parent))

        trailing = TrailingAction(label=self.label1)

        e.appendChild(trailing.render(parent))
        # javascript.mdc.topAppBar.MDCTopAppBar.new(e)
        return e


class ChipSet:
    def __init__(self, chip):
        self.chip = chip

    def render(self, parent):

        if isinstance(self.chip, InputChip) or isinstance(self.chip, ActionChip):

            e = maketag(
                "span", {"class": "mdc-evolution-chip-set", "role": "grid"})
            parent.appendChild(e)

            chip_set = maketag(
                "span", {"class": "mdc-evolution-chip-set__chips", "role": "presentation"})

            e.appendChild(chip_set)

            chip_set.appendChild(self.chip.render(parent))

            return e

        return None


class Slider:
    def __init__(self, value, _min, _max, label, onChanged=None):
        self.value = value
        self.min = _min
        self.max = _max
        self.label = label
        # TODO: 实现 onChanged 的绑定
        self.onChanged = onChanged

    def render(self, parent):

        e = maketag("div", {"class": "mdc-slider"}, style={'width': '200px'})
        parent.appendChild(e)

        input_attr = {"class": "mdc-slider__input", "type": "range", "min": str(self.min), "max": str(
            self.max), "value": str(self.value), "name": "volume", "aria-label": self.label}
        e.appendChild(maketag("input", input_attr))

        track = maketag("div", {"class": "mdc-slider__track"})
        e.appendChild(track)

        track.appendChild(
            maketag("div", {"class": "mdc-slider__track--inactive"}))

        tmp = maketag("div", {"class": "mdc-slider__track--active"})
        track.appendChild(tmp)

        tmp.appendChild(
            maketag("div", {"class": "mdc-slider__track--active_fill"}))

        thumb = maketag("div", {"class": "mdc-slider__thumb"})
        thumb.appendChild(maketag("div", {"class": "mdc-slider__thumb-knob"}))

        e.appendChild(thumb)
        javascript.mdc.slider.MDCSlider.new(e)
        return e


def _make_svg(tag, attrs):
    xmlns = 'http://www.w3.org/2000/svg'
    elt = javascript.document.createElementNS(xmlns, tag)
    for k, v in attrs.items():
        elt.setAttribute(k, v)
    return elt
